package main

import "fmt"

// 如果一个对象的实现方法会根据自身的状态而改变，就可以使用状态模式。
// 举个例子：假设有一个开门的方法，门的状态在一开始是“关闭”，
// 你可以执行open方法和close方法，当你执行了open方法，门的状态就变成了“开启”，
// 再执行open方法就不会执行开门的功能，而是返回“门已开启”，如果执行close方法，
// 门的状态就变成了“关闭”，再执行close方法就不会执行关门的功能，而是返回“门已关闭”。

type state interface {
	open(*door)
	close(*door)
}
type door struct {
	opened       state
	closed       state
	damaged      state
	currentState state
}

func (d *door) open() {
	d.currentState.open(d)
}
func (d *door) close() {
	d.currentState.close(d)
}
func (d *door) setState(s state) {
	d.currentState = s
}

// 开启状态
type opened struct{}

func (o *opened) open(d *door) {
	fmt.Println("门已开启")
}
func (o *opened) close(d *door) {
	fmt.Println("关闭成功")
}

// 关闭状态
type closed struct{}

func (c *closed) open(d *door) {
	fmt.Println("开启成功")
}
func (c *closed) close(d *door) {
	fmt.Println("门已关闭")
}

// 损坏状态
type damaged struct{}

func (a *damaged) open(d *door) {
	fmt.Println("门已损坏，无法开启")
}
func (a *damaged) close(d *door) {
	fmt.Println("门已损坏，无法关闭")
}

func ExampleState() {
	door := &door{}

	// 开启状态
	opened := &opened{}
	door.setState(opened)
	door.open()
	door.close()

	// 关闭状态
	closed := &closed{}
	door.setState(closed)
	door.open()
	door.close()

	// 损坏状态
	damaged := &damaged{}
	door.setState(damaged)
	door.open()
	door.close()
}
